/*
 * times.c
 *
 *  Created on: 13.10.2012
 *      Author: md5sum@alexsp.ru
 */

#include "global.h"
#include <util/crc16.h>
#include <avr/eeprom.h>
#include <util/atomic.h>

EEMEM static times_array_elem_t times_array_eemem[7][POINTS_ON_DAY];
static uint16_t times_array_crc;
EEMEM static uint16_t times_array_crc_eemem;

EEMEM static int16_t heater_temp_max_eemem; // максимальная температура для нагревателя ~80-90 град
EEMEM static int16_t heater_temp_min_eemem; // минимальная температура для нагревателя при которой опять включаем нагрев
EEMEM static int16_t radiator_temp_offset_eemem; //температура отключения насоса - относительно температуры помещения
EEMEM static int16_t error_temp_eemem;

void init_times_array(){
	uint8_t i,j;
	for (i=0;i<7;i++) {
		for (j=1;j<POINTS_ON_DAY;j++) {
			times_array[i][j].termo=0;
			times_array[i][j].time=0x90;
		}
		times_array[i][0].termo=20;
		times_array[i][0].time=0;
	}
	heater_temp_min=40;
	heater_temp_max=80;
	radiator_temp_offset=10;
	error_temp=5;
}

uint8_t get_next_times(tm *t) {
	uint8_t i;
	uint8_t ntime=0xff;
	uint8_t ctime,day_w;
	day_w=t->day_w;
	ctime=t->hour*6+(t->min/10);
	for (i=0;i<POINTS_ON_DAY;i++) {
		if ((ctime<times_array[day_w][i].time)&&(times_array[day_w][i].time!=0x90)) {
			ntime=times_array[day_w][i].time;
			break;
		}
	}
	if (ntime==0xff) ntime=144;

	return (uint8_t)ntime;
}

int8_t get_termo_for_time(uint16_t t,uint8_t d_w){
	uint8_t i=t/144;
	uint8_t j;
	uint8_t weekday;
	weekday=(d_w+i)>6?0:(d_w+i);
	int8_t tmp=10;
	for (j=0;j<POINTS_ON_DAY;j++)
		if (times_array[weekday][j].time<=(t % 144))
			tmp=times_array[weekday][j].termo;

	return tmp;
}

void store_config(){
	uint8_t *p;
	uint8_t i;

	p=(uint8_t *)times_array;

	times_array_crc=0xffff;

	for (i=0;i<sizeof(times_array);i++) times_array_crc=_crc16_update(times_array_crc,*(p++));
	p=(uint8_t *)&heater_temp_max;
	times_array_crc=_crc16_update(times_array_crc,*(p++));
	times_array_crc=_crc16_update(times_array_crc,*(p++));
	p=(uint8_t *)&heater_temp_min;
	times_array_crc=_crc16_update(times_array_crc,*(p++));
	times_array_crc=_crc16_update(times_array_crc,*(p++));
	p=(uint8_t *)&radiator_temp_offset;
	times_array_crc=_crc16_update(times_array_crc,*(p++));
	times_array_crc=_crc16_update(times_array_crc,*(p++));
	p=(uint8_t *)&error_temp;
	times_array_crc=_crc16_update(times_array_crc,*(p++));
	times_array_crc=_crc16_update(times_array_crc,*(p++));
	//calc crc for next config items

	ATOMIC_BLOCK(ATOMIC_RESTORESTATE){
		eeprom_update_block(times_array,times_array_eemem,sizeof(times_array));
		eeprom_update_word((uint16_t *)&heater_temp_max_eemem,heater_temp_max);
		eeprom_update_word((uint16_t *)&heater_temp_min_eemem,heater_temp_min);
		eeprom_update_word((uint16_t *)&radiator_temp_offset_eemem,radiator_temp_offset);
		eeprom_update_word((uint16_t *)&error_temp_eemem,error_temp);
		// write next config items
		eeprom_update_word(&times_array_crc_eemem,times_array_crc);
	}
}

void read_config(){
	uint16_t n_crc=0xffff;
	uint8_t *p;
	uint8_t i;

	eeprom_read_block(times_array,times_array_eemem,sizeof(times_array));
	heater_temp_max=eeprom_read_word((uint16_t *)&heater_temp_max_eemem);
	heater_temp_min=eeprom_read_word((uint16_t *)&heater_temp_min_eemem);
	radiator_temp_offset=eeprom_read_word((uint16_t *)&radiator_temp_offset_eemem);
	error_temp=eeprom_read_word((uint16_t *)&error_temp_eemem);
	// read next config items
	times_array_crc = eeprom_read_word(&times_array_crc_eemem);

	p=(uint8_t *)times_array;
	for (i=0;i<sizeof(times_array);i++) n_crc=_crc16_update(n_crc,*(p++));
	p=(uint8_t *)&heater_temp_max;
	n_crc=_crc16_update(n_crc,*(p++));
	n_crc=_crc16_update(n_crc,*(p++));
	p=(uint8_t *)&heater_temp_min;
	n_crc=_crc16_update(n_crc,*(p++));
	n_crc=_crc16_update(n_crc,*(p++));
	p=(uint8_t *)&radiator_temp_offset;
	n_crc=_crc16_update(n_crc,*(p++));
	n_crc=_crc16_update(n_crc,*(p++));
	p=(uint8_t *)&error_temp;
	n_crc=_crc16_update(n_crc,*(p++));
	n_crc=_crc16_update(n_crc,*(p++));
	// calc crc for next config items

	if (times_array_crc!=n_crc) {
		flags|=FLG_CONG_ERR;
		init_times_array();
		store_config();
		//TODO error config
	}
}

uint8_t get_count_t_on_day(uint8_t dayw){
	uint8_t i;
	uint8_t cnt=0;
	for (i=0;i<POINTS_ON_DAY;i++) {
		if (times_array[dayw][i].time!=0x90) cnt++;
	}
	return cnt;
}

void times_clear_to_end(uint8_t wd,uint8_t ind){
	uint8_t i;
	for (i=ind;i<POINTS_ON_DAY-1;i++) {
		times_array[wd][i]=times_array[wd][i+1];
	}
	times_array[wd][POINTS_ON_DAY-1].time=0x90;
	times_array[wd][POINTS_ON_DAY-1].termo=0;
}
/*
uint8_t get_time_on_index(uint8_t i, uint8_t ti){
	return times_array[i][ti].time;
}
uint8_t get_temp_on_index(uint8_t i, uint8_t ti){
	return times_array[i][ti].termo;
}
*/
